/** 
  1.单个元素验证
  $("#b").easyvalidate([opt]); 
*
*/




/** 
 *  信息提示优先级由高到低
 *  1 页面配置 easymessage="equal:和a输入不同;length:长度不正确"  
 *  2 $.validate.defaults对象中对应验证  $.validate.easymessage.require:不能为空
 *  3 $.validate.judge 对象中对应验证返回方法 ei._error 此方法中定义的信息 
 *  4 _easyinput 对象中的 message 全局
*/
(function(){
	$.validate = $.validate || {};
	$.extend($.validate,{  
		defaults:{
			    easytip : true, // easyform 、easyinput是否 开启提示
			    "real-time":true,// 失去鼠标焦点验证
			    left: 0,
			    top: 0,
	            position: "bottom",     //left ,top ,right ,bottom
	            disappear: "lost-focus",//self, other, lost-focus, none, N seconds
	            speed: "fast",
	            theme: "blue",
	            arrow: "bottom",        //top, left, bottom, right
	            "borderred" : true,
	            onshow: null,
	            onclose: null,
	            style: {}
		},
		easymessage :{
			 "require" : "不能为空",
	    	 "char-normal":"只能为英文、数字、下划线",
	    	 "min-length":"长度不能小于最小值", 
		},
		judge :{
		  "require"    : function(ei, v, r, m) {  
 	            if (v || Number(v) > 0) 
 	                return ei._success("require"); 
 	            else 
 	                return ei._error("require",(m?m:"不能为空")); 
 	        },
 	       "length": function (ei, v, p, m)
           {    
               var range = p.split("-"); 
               //如果长度设置为 length:6 这样的格式
               if (range.length == 1) range[1] = range[0];
               
               if (v.length < range[0] || v.length > range[1])
            	   
                   return ei._error("length",(m?m:(range.length == 1 ? "长度应为"+range[0]:"长度应在"+range[0]+"和"+range[1]+"之间")));
               
               else
                   return ei._success_rule("length");
           },
           "number" : function(ei, v, p, m)
           {
        	   if(typeof (Number(p))) 
        		   return ei._success_rule("number"); 
        	   else
        		   return ei._error("require",(m?m:"只能为数字")); 
           },
           "integer" : function(ei, v, p,m)
           {
        	   if((Number(p) || Number(p) == 0) && parseInt(Number(p)) == Number(p)) 
        		   return ei._success_rule("number"); 
        	   else
        		   return ei._error("require",(m?m:"只能为整数")); 
           },
            "char-normal": function (ei, v, p,m)
            {
                if (false == /^\w+$/.test(v))
                    return ei._error("char-normal");
                else
                    return ei._success_rule("char-normal",(m?m:"只能为英文、数字、下划线"));
            },

            "char-chinese": function (ei, v, p, m)
            {
                if (false == /^([\w]|[\u4e00-\u9fa5]|[ 。，、？￥“‘！：【】《》（）——+-])+$/.test(v))
                    return ei._error("char-chinese",(m?m:"只能为中文、英文、数字、下划线、中文标点符号"));
                else
                    return ei._success_rule("char-chinese");
            },

            "char-english": function (ei, v, p , m)
            {
                if (false == /^([\w]|[ .,?!$'":+-])+$/.test(v))
                    return ei._error("char-english",(m?m:"只能为英文、数字、下划线、英文标点符号"));
                else
                    return ei._success_rule("char-english");
            },

            "email": function (ei, v, p, m)
            {
                if (false == /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(v))
                    return ei._error("email",m?m:"Email格式有误");
                else
                    return ei._success_rule("email");
            }, 

            "equal": function (ei, v, p, m)
            { 
            	
                var pair = $(p) ,pairVal = pair.val() ;
                if ( pairVal != "" && (0 == pair.length || pair.val() != v))
                    return ei._error("equal",m);
                else
                    return ei._success_rule("equal");
            },

            "ajax": function (ei, v, p, m)
            {
                // 为ajax处理注册自定义事件
                // HTML中执行相关的AJAX时，需要发送事件 easyinput-ajax 来通知 easyinput
                // 该事件只有一个bool参数，easyinput 会根据这个值判断ajax验证是否成功
                ei.input.delegate("", "easyinput-ajax", function (e, p)
                {
                    ei.input.unbind("easyinput-ajax");

                    if (false == p)
                        return ei._error("ajax",m);
                    else
                        return ei._success_rule("ajax");
                });

                eval(p);
            },

            "date": function (ei, v, p, m)
            {
                if (false == /^(\d{4})-(\d{2})-(\d{2})$/.test(v))
                    return ei._error("date",(m ? m : "日期格式有误"));
                else
                    return ei._success_rule("date");
            },

            "time": function (ei, v, p, m)
            {
                if (false == /^(\d{2}):(\d{2}):(\d{2})$/.test(v))
                    return ei._error("time",(m ? m : "时间格式有误"));
                else
                    return ei._success_rule(v);
            },

            "datetime": function (ei, v, p, m)
            {
                if (false == /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/.test(v))
                    return ei._error("datetime",(m ? m : "日期格式有误"));
                else
                    return ei._success_rule("datetime");
            },

            "money": function (ei, v, p, m)
            {
                if (false == /^([1-9][\d]{0,7}|0)(\.[\d]{1,2})?$/.test(v))
                    return ei._error("money",(m ? m : "金额格式有误"));
                else
                    return ei._success_rule("money");
            },

            "uint": function (ei, v, p, m)
            {
                v = parseInt(v);
                p = parseInt(p);

                if (isNaN(v) || isNaN(p) || v < p || v < 0)
                    return ei._error("uint",(m ?  m :"数字在"+v+"-"+p+"之间"));
                else
                    return ei._success_rule("uint");
            } 
		},
		themes:{  
		        black: {
		            color: "rgba(238,238,238,1)",
		            "background-color": "rgba(75,75,75,0.8",
		            "border": "0px solid rgba(75,75,75,0.8)",
		            "border-radius": 5
		        },
		        blue: {
		            color: "rgba(255,255,255,1)",
		            "background-color": "rgba(51,153,204,0.8)",
		            "border": "0px solid rgba(51,153,204,0.8)",
		            "border-radius": 5
		        },
		        red: {
		            color: "rgba(255,255,255,1)",
		            "background-color": "rgba(255,102,102,0.9)",
		            "border": "0px solid rgba(255,102,102,0.9)",
		            "border-radius": 5
		        },
		        white: {
		            color: "rgba(102,102,102,1)",
		            "background-color": "rgba(255,255,255,0.9)",
		            "border": "0px solid rgba(255,255,255,0.9)",
		            "border-radius": 5
		        }
    
	}});
})();

(function ($, window, document, undefined)
		{
		    /*
		     构造函数
		     **/
		    var _easyform = function (ele, opt)
		    {
		        this.form = ele; 
		        this.options = $.extend({},$.validate.defaults, opt);  
		        this.inputs = []; 
		        this.counter = 0; 
		    };

		    //方法
		    _easyform.prototype = {

		        init: function ()
		        { 
		            this._load();
		            return this;
		        },

		        _load: function ()
		        {
		            this.inputs.splice(0, this.inputs.length);
		            var ev = this;

		            this.form.find("input:visible,select:visible,textarea:visible").each(function (index, input)
		            {
		                //排除 hidden、button、submit、checkbox、radio、file
		                if (input.type != "hidden" && input.type != "button" && input.type != "submit" && input.type != "checkbox" && input.type != "radio" && input.type != "file")
		                {    
		                	var checker = $(input).easyvalidate(); 
		                	debugger;
		                	 checker.error = function (e)
		                     { 
		                         ev.is_submit = false;
		                         ev.result.push(e);

		                         if (!!ev.error)    //失败事件
		                             ev.error(e);
		                     };
		                     ev.inputs.push(checker);
		                }
		            });
		        },
		        validate : function(){ 
		            for (var index in this.inputs)
		            {
		                this.inputs[index].validation();
		            }
		        }

		    };

		    //添加到jquery
		    $.fn.easyform = function (options)
		    {
		        var validation = new _easyform(this, options);

		        return validation.init();
		    };
		})(jQuery, window, document);




(function ($, window, document, undefined)
		{
		    //单个input的检查器构造函数
		    var _easyinput = function (input, opt)
		    { 
		    	//counter 计数器，记录已经有多少个条件成功
		    	//error 、success 事件
		        this.input = input  , this.is_error = false , this.error = null,this.options = {rules:[],tipoptions:{}}  ,
		        
		        this.counter = 0    , this.success = null   , this.message = "格式错误!" ;
		        
		        var   o = {} , r = {} , m = {} ,rules = [];
		        
		        var rule_str = this.input.attr("easyrule") , _rules = !!rule_str ? rule_str.split(";") : [] ;
		        		
		        msg_str = this.input.attr("easymessage")   ,  _msgs = !!msg_str ? msg_str.split(";") : []   ;
		        		 
		        //生成  {"length":"length:1-2","require":""} 格式 
		        $.each(_rules,function(i,e){  
		        		 if(!e ) return ; //continue;
		        		 
		        		 var  p = e.indexOf(":") , _r = e.substr(0, p) ;
		        		 
		        		 if (-1 == p) _r = e;
		        		 
		        		 if($.validate.judge.hasOwnProperty(_r))  r[_r] = e    //该属性是验证属性
		        			 
		        		 else  o[_r] = e.substr(p + 1);                        //该属性验证是 easyform普通属性
		        		 
		        });
		       
		        
		        //生成  {"length":"长度太长","require":"必填"} 格式 
		        $.each(_msgs,function(i,e){
		        	
	        		 if(!e ) return ; //continue;
	        		 
	        		 var  p = e.indexOf(":") , _r = e.substr(0, p) ,_m =  e.substr(p + 1);
	        		 
	        		 if($.validate.judge.hasOwnProperty(_r) && -1 != p)   m[_r] = _m ; 
	        		 
	           });
		        
	
		        //重写 页面上的验证
		        for(e in opt){
		        	
		        	if($.validate.judge.hasOwnProperty(e)) r[e] = opt[e] ;     
		        	
		        	else if( e == "easymessage" &&  typeof(opt[e]) =="object")
		        	
		        	{
		        		for(a in opt[e]){
		        			if($.validate.judge.hasOwnProperty(a))  m[a] = opt[e][a];
		        		} 
		        	}
		        	
		        	else  o[e] = opt[e] ;
		        	
		        }		
		        
		        m =   $.extend({},$.validate.easymessage,m);
		        
		        o =   $.extend({},$.validate.defaults,o);
		        		  
		        for (e in r)
		           {    //有:号 
		        	    var s = r[e] ;
		        	    
		        	    if(!s) continue; 
		        	    
		        	    var p = s.indexOf(":")  , param = "" ;
		              
		                if (-1 != p)   param = s.substr(p + 1); 
		                
		                rules.push({"rule" : $.validate.judge[e], "rulename":e, "param": param, "message" : m[e]});
		                
	                }  
		        
		        this.options.rules = rules; 
		        this.options.tipoptions = o;
		        
		    };

		    //单个input的检查器
		    _easyinput.prototype = { 
		        init: function ()
		        {   	   
			            var easyinput = this;
			            if (this.options.tipoptions["real-time"])//失去鼠标焦点检查
			            {
			                this.input.blur(function ()
			                {   
			                    easyinput.validation();
			                });
			            }  
			            this.options.easytip = $(this.input).easytip(this.options.tipoptions);
		            return this;
		        },  
		        /**
		         * 规则判断
		         * */
		        validation: function ()
		        {    
		            this.value = this.input.val();
		            this.counter = 0;   //计数器清零 
		            this.is_error = false;  
		            for (var i = 0; i < this.options.rules.length; i++)
		            { 
		            	 this.options.rules[i].rule(this, this.value, this.options.rules[i].param,this.options.rules[i].message);
		            }
		        }, 

		        _error: function (rule,_msg)
		        {    
		            if (!!this.error)
		                this.error(this.input, rule);

		            if (false == this.is_error)
		            {
		            	//扩展提示 
		                var  msg = _msg ? _msg : this.message;  //参数 msg 
		                if (!!this.options.easytip)
		                {
		                    this.options.easytip.show(msg);
		                }

		                this.is_error = true;
		            }

		            return false;
		        },

		        _success: function ()
		        {
		            if (!!this.success)
		                this.success(this.input);

		            return true;
		        },

		        _success_rule: function (rule)
		        {
		            this.counter += 1;

		            if (this.counter == this.options.rules.length)
		                this._success();

		            return true;
		        }, 
		    };

		    $.fn.easyvalidate = function (options)
		    {
		        var check = new _easyinput(this, options);

		        return check.init();
		    };

})(jQuery, window, document);





(function ($, window, document, undefined)
{ 
    var _easytip = function (ele, opt)
    {
        this.parent = ele , this.padding = 0  , this.id = "easytip-div-main" + ele[0].id; 
        
        var tipoptions = ele.attr("easytip") , tipopts = {};
        
        tipoptions = (!!tipoptions ? tipoptions.split(";") : undefined); 
        if (!!tipoptions)
        {
	            var options = Object();
	            var index;
	            for (index in tipoptions)
	            {
	                var temps = tipoptions[index];
	                var p = temps.indexOf(":");
	
	                if (-1 == p)continue;
	
	                var temp = [];
	                temp[0] = temps.substring(0, p);
	                temp[1] = temps.substring(p + 1);
	
	                options[temp[0]] = temp[1];
	            }
	            tipopts = options;
          }  
        // 继承  根属性  、页面上的属性  、传值属性 
        this.options = $.extend({},$.validate.defaults,tipopts, opt);   
    };

    _easytip.prototype = {

        init: function ()
        {
            var tip = $("#" + this.id);

            if (tip.length == 0)
            {
                $(document.body).append("<div id=\"" + this.id + "\"><div class=\"easytip-text\"></div></div>");

                tip = $("#" + this.id);
                var text = $("#" + this.id + " .easytip-text");

                tip.css({
                    "text-align": "left",
                    "display": "none",
                    "position": "absolute"
                });

                text.css({
                    "text-align": "left",
                    "padding": "10px",
                    "min-width": "120px"
                });

                tip.append("<div class=\"easytip-arrow\"></div>");
                var arrow = $("#" + this.id + " .easytip-arrow");
                arrow.css({
                    "padding": "0",
                    "margin": "0",
                    "width": "0",
                    "height": "0",
                    "position": "absolute",
                    "border": "10px solid"
                });
            }

            return this;
        },

        _size: function ()
        {
            var parent = this.parent;
            var tip = $("#" + this.id);


            if (tip.width() > 300)
            {
                tip.width(300);
            }
        },

        _css: function ()
        {
            var tip = $("#" + this.id);
            var text = $("#" + this.id + " .easytip-text");
            var arrow = $("#" + this.id + " .easytip-arrow");

            text.css($.validate.themes[this.options.theme]); 
            arrow.css("border-color", "transparent transparent transparent transparent");

            if (this.options.style != null && typeof(this.options.style) == "object")
            {
                text.css(this.options.style);
            }
        },

        _arrow: function ()
        {
            var tip = $("#" + this.id);
            var text = $("#" + this.id + " .easytip-text");
            var arrow = $("#" + this.id + " .easytip-arrow");

            switch (this.options.arrow)
            {
                case "top":
                    arrow.css({
                        "left": "25px",
                        "top": -arrow.outerHeight(),
                        "border-bottom-color": text.css("borderTopColor")
                    });
                    break;

                case "left":
                    arrow.css({
                        "left": -arrow.outerWidth(),
                        "top": tip.innerHeight() / 2 - arrow.outerHeight() / 2,
                        "border-right-color": text.css("borderTopColor")
                    });
                    break;

                case "bottom":
                    arrow.css({
                        "left": "25px",
                        "top": tip.innerHeight(),
                        "border-top-color": text.css("borderTopColor")
                    });
                    break;

                case "right":
                    arrow.css({
                        "left": tip.outerWidth(),
                        "top": tip.innerHeight() / 2 - arrow.outerHeight() / 2,
                        "border-left-color": text.css("borderTopColor")
                    });
                    break;
            }
        },

        _position: function ()
        {
            var tip = $("#" + this.id);
            var text = $("#" + this.id + " .easytip-text");
            var arrow = $("#" + this.id + " .easytip-arrow");
            var offset = $(this.parent).offset();
            var size = {width: $(this.parent).outerWidth(), height: $(this.parent).outerHeight()};

            switch (this.options.position)
            {
                case "top":

                    tip.css("left", offset.left - this.padding);
                    tip.css("top", offset.top - tip.outerHeight() - arrow.outerHeight() / 2);
                    this.options.arrow = "bottom";

                    break;

                case "left":

                    tip.css("left", offset.left - tip.outerWidth() - arrow.outerWidth() / 2);
                    tip.css("top", offset.top - (tip.outerHeight() - size.height) / 2);
                    this.options.arrow = "right";

                    break;

                case "bottom":

                    tip.css("left", offset.left - this.padding);
                    tip.css("top", offset.top + size.height + arrow.outerHeight() / 2);
                    this.options.arrow = "top";

                    break;

                case "right":

                    tip.css("left", offset.left + size.width + arrow.outerWidth() / 2);
                    tip.css("top", offset.top - (tip.outerHeight() - size.height) / 2);
                    this.options.arrow = "left";

                    break;
            }

            var left = parseInt(tip.css("left"));
            var top = parseInt(tip.css("top"));

            tip.css("left", parseInt(this.options.left) + left);
            tip.css("top", parseInt(this.options.top) + top);
        },

        show: function (msg)
        {
            var tip = $("#" + this.id);
            var text = $("#" + this.id + " .easytip-text");
            var arrow = $("#" + this.id + " .easytip-arrow");
            var speed = this.options.speed;
            var disappear = this.options.disappear;
            var parent = this.parent;
	       	if(this.options["borderred"]){ 
	       	   parent.addClass("err_border");
	    	}  
            text.html(msg); 
            this._size();
            this._css();
            this._position();
            this._arrow();
            var that = this;

            var onshow = this.options.onshow;
            var onclose = this.options.onclose;

            tip.fadeIn(speed, function ()
            {
                if (!!onshow)    onshow({parent: parent, target: tip[0]});

                if (!isNaN(disappear))
                {
                    setTimeout(function ()
                    { 
                    	that.fadeOut(speed,onclose ,{parent: parent, target: tip[0]});  
                    }, disappear);
                }
                else if (disappear == "self" || disappear == "other")
                {
                    $(document).click(function (e)
                    {
                        if (disappear == "self" && e.target == text[0])
                        {
                        	that.fadeOut(speed,onclose, {parent: parent, target: tip[0]});
                        	$(document).unbind("click");
                        }
                        else if (disappear == "other" && e.target != tip[0])
                        {
                        	that.fadeOut(speed,onclose,{parent: parent, target: tip[0]});
                        	$(document).unbind("click");
                        }
                    });
                }
                else if (disappear == "lost-focus")
                {
                    $(parent).focusout(function ()
                    {
                    	that.fadeOut(speed,onclose,{parent: parent, target: tip[0]});
                    	$(parent).unbind("focusout");
                    });
                }
            });
        },
        fadeOut : function(speed,onclose,param){
        	 var tip = $("#" + this.id);
        	 tip.fadeOut(speed, function ()
             {
	             if (!!onclose)    onclose(param);
            }); 
        	 if(this.options["borderred"]){ 
        		 this.parent.removeClass("err_border");
        	 } 
        },
        close: function ()
        { 
            var tip = $("#" + this.id);
            var parent = this.parent; 
            var onclose = this.options.onclose; 
            this.fadeOut(this.options.speed,onclose,{parent: parent, target: tip[0]}); 
        }
    };

    $.fn.easytip = function (options)
    {
        var tip = new _easytip(this, options);

        return tip.init();
    };

})(jQuery, window, document);